package com.bwjf.dzfp.common.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.json.JsonObject;
import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

public class WXApi {
	static Logger logger = Logger.getLogger(WXApi.class);

	// 根据授权code获取opid接口
	private final String snsapi_base_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
	// 获取根据openid获取用户信息
	private final String snsapi_url_xx = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
	// 获取token接口
	private final String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

	private final String snsapi_code_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=URL&response_type=code&scope=snsapi_base&state=WXSQ&connect_redirect=1#wechat_redirect";

	// jsapi 调用凭据 时效7200秒
	private final String jsapi_ticket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";

	private String appid;// appid
	private String appsecret;// 密匙

	private long timeout = 1 * 60 * 60 * 1000;// 过期时间
	private long last_token_time = 0;// 最后一次获取token时间
	private long expiredTime = 0;// token过期时间
	private String access_token = "";// access_token

	public WXApi() {

	}

	/**
	 * 通过微信返回的授权码获取openId
	 * 
	 * @param code
	 *            授权码
	 * @return
	 */
	public String getOpenId(String code) {
		String openId = null;
		String token = getToken();// 获取access_token
		if (token == null || token.equals("")) {
			logger.error("-----------------------------1.获取到微信access_token失败");
		} else {
			String url = snsapi_base_url.replace("APPID", appid)
					.replace("SECRET", appsecret).replace("CODE", code);
			String openidJson = HttpUtils.httpGet(url);// 获取openid
			JSONObject json = JSONObject.parseObject(openidJson);
			if (json != null) {
				openId = json.getString("openid");
			}
		}
		return openId;
	}

	/**
	 * 获取微信用户基本信息 其中subscribe属性 0：未关注当前公众
	 * 
	 * @param openId
	 *            微信用户唯一标识
	 * @return
	 */
	public JSONObject getWXUserInfo(String openId) {
		String token = getToken();// 获取access_token
		String userurl = snsapi_url_xx.replace("ACCESS_TOKEN", token).replace(
				"OPENID", openId);
		String userJsonStr = HttpUtils.httpGet(userurl);// 获取微信用户基本信息url
		JSONObject userJson = JSONObject.parseObject(userJsonStr);
		return userJson;
	}

	/**
	 * 获取微信用户基本信息 其中subscribe属性 0：未关注当前公众号
	 * 
	 * @param openId
	 *            微信用户唯一标识
	 * @return
	 */
	public boolean isSubscribe(String openId) {
		String token = getToken();// 获取access_token
		String userurl = snsapi_url_xx.replace("ACCESS_TOKEN", token).replace(
				"OPENID", openId);
		String userJsonStr = HttpUtils.httpGet(userurl);// 获取微信用户基本信息url
		JSONObject userJson = JSONObject.parseObject(userJsonStr);
		return !userJson.getString("subscribe").equals("0");
	}

	/**
	 * 获取微信用户基本信息 其中subscribe属性 0：未关注当前公众号
	 * 
	 * @param openId
	 *            微信用户唯一标识
	 * @return
	 */
	public boolean isSubscribe(JSONObject userJson) {
		return userJson.getString("subscribe") != null
				&& !userJson.getString("subscribe").equals("0");
	}

	// 获取token 微信接口调用授权码
	public String getToken() {
		String tokenJson = "";
		String tokenJ = "";
		String url = PropertiesLoad.getTokenUrl();
		if(url!=null){
			if(access_token==null || access_token.equals("") 
					|| new Date().getTime()-expiredTime>0) {
				tokenJ = HttpUtils.httpGet(url);
				JSONObject json = null;
				if(tokenJ != null && tokenJ.startsWith("[")) {
					json =JSONObject.parseObject(tokenJ);
				}else{
					json =JSONArray.parseArray(tokenJ).getJSONObject(0);
				}
				access_token=(String)json.get("accessToken");
				SimpleDateFormat separator = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				Date ssjj = new Date();
				try {
					ssjj = separator.parse((String)json.get("expiredTime"));
					System.out.println("输出过期时间");
				} catch (ParseException e) {
					e.printStackTrace();
				} 
				expiredTime = ssjj.getTime() ;
				System.out.println(expiredTime);
			}
		} else {
			if (access_token == null || access_token.equals("")
					|| new Date().getTime() - last_token_time > timeout) {
				System.out.println("----------------通过其他途径获取授权码");
				String tokenurl = access_token_url.replace("APPID", appid)
						.replace("APPSECRET", appsecret);
				tokenJson = HttpUtils.httpGet(tokenurl);
				JSONObject obj = JSONObject.parseObject(tokenJson);
				access_token = (String) obj.get("access_token");
			}
		}
		return access_token;
	}

	/**
	 * 获取用户临时授权码接口地址
	 * 
	 * @param redirectUri
	 *            回调连接地址
	 * @return
	 */
	public String getTempCodeUrl(String redirectUri) {
		return snsapi_code_url.replace("APPID", appid).replace("URL",
				redirectUri);
	}

	private long last_jsapi_ticket_time = 0;// 最后一次获取token时间
	private String jsapiTicket;

	/**
	 * 获取jsapi ticket
	 * 
	 * @return
	 */
	public String getJsapiTicket() {
		String token = getToken();// 获取access_token
		long currentTime = new Date().getTime();
		if (jsapiTicket != null
				&& currentTime - last_jsapi_ticket_time < timeout) {
			return jsapiTicket;
		}
		String jsapiTicketURL = jsapi_ticket.replace("ACCESS_TOKEN", token);
		String jsapiJsonStr = HttpUtils.httpGet(jsapiTicketURL);// 获取微信用户基本信息url
		JSONObject result = JSONObject.parseObject(jsapiJsonStr);
		if (!"0".equals(result.getString("errcode"))) {// 是否成功
			jsapiTicket = null;
			return null;
		}
		last_jsapi_ticket_time = new Date().getTime();
		return result.getString("ticket");
	}

	/**
	 * 获取微信jsAPI相关参数
	 * 
	 * @param currentURL
	 *            需要调用jsapi的页面的完整url
	 * @return jsapi相关参数
	 */
	public Map<String, String> getJsapiSign(HttpServletRequest request) {
		StringBuilder currentURL = new StringBuilder();
		currentURL.append(request.getScheme()).append("://")
				.append(request.getServerName());
		if (!"80".equals(request.getServerPort() + "")) {
			currentURL.append(":").append(request.getServerPort());
		}
		currentURL.append(request.getContextPath()).append(
				request.getServletPath());

		if (request.getQueryString() != null) {
			currentURL.append("?").append(request.getQueryString()); // 参数
		}
		String jsapiTicket = getJsapiTicket();
		System.out.println(currentURL.toString());
		return sign(jsapiTicket, currentURL.toString());
	}

	public static void main(String[] args) {
		WXApi wxApi = new WXApi();
		System.out.println(wxApi.getToken());
		System.out.println(wxApi.getToken());
	}

	public void setAppid(String appid) {
		this.appid = appid;
	}

	public void setAppsecret(String appsecret) {
		this.appsecret = appsecret;
	}

	private Map<String, String> sign(String jsapi_ticket, String url) {
		Map<String, String> ret = new HashMap<String, String>();
		String nonce_str = create_nonce_str();
		String timestamp = create_timestamp();
		String string1;
		String signature = "";

		// 注意这里参数名必须全部小写，且必须有序
		string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str
				+ "&timestamp=" + timestamp + "&url=" + url;
		// System.out.println(string1);

		try {
			MessageDigest crypt = MessageDigest.getInstance("SHA-1");
			crypt.reset();
			crypt.update(string1.getBytes("UTF-8"));
			signature = byteToHex(crypt.digest());
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		ret.put("url", url);
		ret.put("jsapi_ticket", jsapi_ticket);
		ret.put("nonceStr", nonce_str);
		ret.put("timestamp", timestamp);
		ret.put("signature", signature);
		ret.put("appId", appid);
		return ret;
	}

	private static String byteToHex(final byte[] hash) {
		Formatter formatter = new Formatter();
		for (byte b : hash) {
			formatter.format("%02x", b);
		}
		String result = formatter.toString();
		formatter.close();
		return result;
	}

	private static String create_nonce_str() {
		return UUID.randomUUID().toString();
	}

	private static String create_timestamp() {
		return Long.toString(System.currentTimeMillis() / 1000);
	}
}
